#include "InputSourceManager.h"
#include "StreamPullerInputSource.h"
#include "HdmiInputSource.h"
#include "SqlTableHelper.h"

namespace Media{
    InputSourceManager::Ptr InputSourceManager::Instance(){
        static auto ptr = std::make_shared<InputSourceManager>();
        return ptr;
    }
    InputSourceManager::InputSourceManager(){
        m_sql = SqlTableOp::Instance();
        init();
    }
    InputSourceManager::~InputSourceManager()= default;


    bool InputSourceManager::AddSource(const inputSourceTable& config, uint32_t& id){
        if(m_sql->InsertTable<inputSourceTable>(config, id)){
            //create inputSource
            SourceInterfaceEnum inType = SourceInterConnectMap[config.m_con_type];
            SourceMediaType mediaType = VIDEO;
            if(config.m_type == MediaVideo){
                mediaType = VIDEO;
            }else if(config.m_type == MediaAudio){
                mediaType = AUDIO;
            }else if(config.m_type == MediaAll){
                mediaType = VA;
            }else{
                return false;
            }

            SourceConfig sConfig;
            sConfig.m_sourceType = INPUT;
            sConfig.m_isCustomCreated = config.m_custom;
            sConfig.m_sourceInterface = inType;
            sConfig.m_sourceMediaType = mediaType;
            sConfig.m_sourceContent = config.m_content;

            auto sourcePtr = createInputSource(sConfig);
            if(sourcePtr){
                std::lock_guard<std::recursive_mutex> guard(m_mux);
                m_sources[id] = sourcePtr;
                return true;
            }
        }
        return false;
    }
    bool InputSourceManager::RemoveSource(uint32_t id){
        if(m_sql->DelTable<inputSourceTable>(id)){
            std::lock_guard<std::recursive_mutex> guard(m_mux);
            if(m_sources.find(id) != m_sources.end()){
                m_sources.erase(id);
                return true;
            }
        }
        return false;
    }
    bool InputSourceManager::GetOneSourceConfig(uint32_t id, inputSourceTable& config){
        return m_sql->GetOneTable<inputSourceTable>(id, config);
    }
    bool InputSourceManager::GetAllSourceConfig(std::vector<inputSourceTable>& configs){
        return m_sql->GetAllTable<inputSourceTable>(configs);
    }   
    
    InputSource::Ptr InputSourceManager::GetSource(uint32_t id){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        InputSource::Ptr source;
        if(m_sources.find(id) != m_sources.end()){
            source = m_sources[id];
        }
        return source;
    }

    InputSource::Ptr InputSourceManager::createInputSource(const SourceConfig& config){
        InputSource::Ptr source;
        if(config.m_sourceInterface == NETWORK){
            source = std::make_shared<StreamPullerInputSource>(config.m_sourceMediaType, config.m_sourceContent);
        }else if(config.m_sourceInterface == HDMI){
            source = HdmiInputSource::Instance();
        }
        return source;
    }

    void InputSourceManager::init(){
        //get all inputSource from sql
        std::vector<inputSourceTable> tbs;
        if(m_sql->Instance()->GetAllTable<inputSourceTable>(tbs)){
            for(const auto& tb:tbs){
                if(SourceInterConnectMap.find(tb.m_con_type) != SourceInterConnectMap.end()){
                    SourceInterfaceEnum inType = SourceInterConnectMap[tb.m_con_type];
                    SourceMediaType mediaType = VIDEO;
                    if(tb.m_type == MediaVideo){
                        mediaType = VIDEO;
                    }else if(tb.m_type == MediaAudio){
                        mediaType = AUDIO;
                    }else if(tb.m_type == MediaAll){
                        mediaType = VA;
                    }else{
                        continue;
                    }

                    SourceConfig config;
                    config.m_sourceType = INPUT;
                    config.m_isCustomCreated = tb.m_custom;
                    config.m_sourceInterface = inType;
                    config.m_sourceMediaType = mediaType;
                    config.m_sourceContent = tb.m_content;
                    auto source = createInputSource(config);
                    if(source){
                        std::lock_guard<std::recursive_mutex> guard(m_mux);
                        m_sources[tb.m_id] = source;
                    }
                }
            }
        }
    }
    void InputSourceManager::inputLocalInterfaceCheck(){
        //todo
    }

}